home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / dosfs / dmsdosfs.000 / dmsdosfs / dmsdosfs-0.6.9b / dmsdos_write.c < prev    next >
C/C++ Source or Header  |  1996-07-29  |  45KB  |  1,547 lines

  1. /*
  2. linux/fs/dmsdos/dmsdos_write.c
  3.  
  4. DMSDOS filesystem: write access functions
  5.  
  6. ******************************************************************************
  7. DMSDOS (Doublespace/Drivespace compressed MSDOS filesystem) for Linux
  8. written 1995,1996 by Frank Gockel
  9.  
  10.     (C) Copyright 1995,1996 by Frank Gockel
  11.  
  12. Some code of the dmsdos filesystem has been copied from the msdos filesystem
  13. so there are the following additional copyrights:
  14.  
  15.     (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
  16.     (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
  17.     (C) Copyright 1992-1995 by Linus Torvalds
  18.  
  19. The DMSDOS filesystem was inspired by the THS filesystem (a simple doublespace
  20. DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.
  21.  
  22. The DMSDOS filesystem is distributed under the Gnu General Public Licence.
  23. See file COPYING for details.
  24. ******************************************************************************
  25.  
  26. */
  27.  
  28. #include <linux/mm.h>
  29. #include <linux/malloc.h>
  30. #include <linux/string.h>
  31. #include <linux/fs.h>
  32. #include <linux/msdos_fs.h>
  33. #include <asm/segment.h>
  34. #include <linux/errno.h>
  35. #include <linux/stat.h>
  36. #include <linux/dmsdos_fs.h>
  37. #include <linux/kernel.h>
  38. #include <linux/sched.h>
  39. #include <linux/ctype.h>
  40. #include <linux/major.h>
  41. #include <linux/blkdev.h>
  42. #include <linux/locks.h>
  43.  
  44. #define PRINTK(X)
  45.  
  46. #include <asm/segment.h>
  47. #include <linux/fcntl.h>
  48.  
  49. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  50. #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  51.  
  52. #define RAW -1
  53.  
  54. extern Dblsb dblsb[];
  55.  
  56. /*
  57.     Write to a file from user space
  58. */
  59. int dmsdos_file_writex(struct inode *inode, struct file *filp, 
  60. #ifdef __FOR_KERNEL_1_3
  61.                        const
  62. #endif
  63.                        char *buf, int count)
  64. {       int cluster;
  65.         int lastcluster;
  66.         int sektor;
  67.         Mdfat_entry mde;
  68.         int new;
  69.         unsigned int offset;
  70.         int cvfnr;
  71.         unsigned char *clusterd;
  72. #ifdef __FOR_KERNEL_1_3
  73.         const
  74. #endif
  75.         unsigned char *b;
  76.         int length;
  77.         int size;
  78.         int canwrite;
  79.         int geschrieben;
  80.         int clustersize;
  81.         int uc;
  82.         int cr;
  83.         char datum;
  84.         int need_cluster;
  85.  
  86.     if (!inode) {
  87.         printk("dmsdos_file_write: inode = NULL\n");
  88.         return -EINVAL;
  89.     }
  90.     /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
  91.     if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
  92.         printk("dmsdos_file_write: mode = %07o\n",inode->i_mode);
  93.         return -EINVAL;
  94.     }
  95. /*
  96.  * ok, append may not work when many processes are writing at the same time
  97.  * but so what. That way leads to madness anyway.
  98.  */
  99.         cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  100.         if(cvfnr<0)
  101.         { printk("DMSDOS: file_writex: cvfnr<0 ???\n");
  102.           return -EINVAL;
  103.         }
  104.         
  105.         if(dblsb[cvfnr].s_comp==READ_ONLY)return -EPERM;
  106.  
  107.     if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
  108.     if (count <= 0) return 0;
  109.     
  110.     clustersize=dblsb[cvfnr].s_sectperclust*SECTOR_SIZE;
  111.     uc=(MSDOS_I(inode)->i_binary>1)?1:0; /* uncompressed forced ? */
  112.     
  113.     clusterd=(unsigned char*)MALLOC(clustersize);
  114.     if(clusterd==NULL)
  115.     { printk("DMSDOS: write_file: no memory!\n");
  116.       return -EIO;
  117.     }
  118.     
  119.     offset=filp->f_pos;
  120.     /* bestimme cluster */
  121.     new=0;
  122.     lastcluster=0;
  123.     cluster=MSDOS_I(inode)->i_start;
  124.     if(cluster==0)
  125.     { /*ersten cluster holen*/
  126.       cluster=allocate_first_cluster(inode->i_sb,cvfnr);
  127.       if(cluster<=0)
  128.       { FREE(clusterd);
  129.         return -ENOSPC;
  130.       }
  131.       MSDOS_I(inode)->i_start=cluster;
  132.       inode->i_dirt=1;
  133.       new=1;
  134.     }
  135.     while(offset>=clustersize)
  136.     { lastcluster=cluster;
  137.       cluster=dbl_fat_nextcluster(inode->i_sb,cluster,cvfnr,NULL);
  138.       if(cluster==0||cluster==1)
  139.       { printk("DMSDOS: file_write: calc_pos: something wrong with fat (0 or 1) in cluster %d\n",
  140.                lastcluster);
  141.         FREE(clusterd);
  142.         return -EIO;
  143.       }
  144.       if(cluster==-1)
  145.       { /* war der letzte, ich brauche einen neuen */
  146.         /*printk("DMSDOS: write_file: calc_pos: need new cluster after cluster %d\n",
  147.                lastcluster);*/
  148.         /* hat der letzte die volle laenge ? */
  149.         dbl_mdfat_value(inode->i_sb,lastcluster,cvfnr,NULL,&mde);
  150.         size=mde.size_hi_minus_1+1;
  151.         if(size!=dblsb[cvfnr].s_sectperclust)
  152.         { /*nein, mist....*/
  153.           /*printk("DMSDOS: write_file: calc_pos: adapting cluster size cluster=%d size=%d\n",
  154.                  lastcluster,size);*/
  155.           if(dmsdos_read_cluster(inode->i_sb,clusterd,lastcluster,cvfnr)<0)
  156.           { FREE(clusterd);
  157.             return -EIO;
  158.           }
  159.           memset(&(clusterd[SECTOR_SIZE*size]),0,
  160.                  (dblsb[cvfnr].s_sectperclust-size)*SECTOR_SIZE);
  161.           /*schreiben(near mdfat&DBLSECTOR_MASK+1)*/
  162.           if( dmsdos_write_cluster(inode->i_sb,clusterd,clustersize,
  163.                                    lastcluster,mde.sector_minus_1+1,
  164.                                    cvfnr,
  165.                                    uc) <0 )
  166.           { FREE(clusterd);
  167.             return -ENOSPC;
  168.           }
  169.         }
  170.         sektor=dbl_mdfat_cluster2sector(inode->i_sb,lastcluster,cvfnr);
  171.         /*printk("DMSDOS: write_file: calc_pos: allocating new cluster...\n");
  172.         */
  173.         cluster=allocate_next_cluster(inode->i_sb,lastcluster,cvfnr);
  174.         /*printk("DMSDOS: write_file: calc_pos: new cluster=%d\n",cluster);
  175.         */
  176.         if(cluster<=0)
  177.         { FREE(clusterd);
  178.           return -ENOSPC;
  179.         }
  180.         /* wuerde noch ein durchlauf folgen, muss die luecke gefuellt 
  181.            werden - ansonsten ists egal */
  182.         if(offset-clustersize>=clustersize)
  183.         {
  184.           /*ganz mit nullen fuellen*/
  185.           /*printk("DMSDOS: zeroing new cluster...\n");*/
  186.           memset(clusterd,0,clustersize);
  187.           /*schreiben(near sektor)*/
  188.           /*printk("DMSDOS: writing zeroed cluster %d...\n",cluster);*/
  189.           dmsdos_write_cluster(inode->i_sb,clusterd,clustersize,cluster,
  190.                                sektor,cvfnr,uc);
  191.           /*printk("DMSDOS: cluster written\n");*/
  192.         }
  193.         new=1;
  194.       }
  195.       offset-=clustersize;
  196.     }
  197.      
  198.     /*printk("DMSDOS: file_write: beginning with cluster %d, lastcluster=%d, new=%d\n",
  199.            cluster,lastcluster,new);*/
  200.       /* in cluster steht die nummer des clusters mit dem ich jetzt
  201.          arbeite;
  202.          der cluster existiert wenn new=0 und wurde evtl mit
  203.          nullen ganz aufgefuellt;
  204.          es ist egal, ob es der letzte in der fatkette ist;
  205.       */
  206.         b=buf;
  207.         geschrieben=0;
  208.         
  209.         if(MSDOS_I(inode)->i_binary==0)goto text_write;
  210.         
  211.         while(count>0)
  212.         {
  213.       if( (offset>0||count<clustersize) &&new==0)
  214.       { /* muss gelesen werden */
  215.         /*printk("DMSDOS: write_file: reading cluster %d...\n",cluster);*/
  216.         dbl_mdfat_value(inode->i_sb,cluster,cvfnr,NULL,&mde);
  217.         length=(mde.size_hi_minus_1+1)*SECTOR_SIZE;
  218.         if(dmsdos_read_cluster(inode->i_sb,clusterd,cluster,cvfnr)<0)
  219.         { printk("DMSDOS: write_file: read_cluster failed!\n");
  220.           FREE(clusterd);
  221.           return -EIO;
  222.         }
  223.           }
  224.           else length= (new==1&&count+offset<clustersize) ?
  225.                                                   count+offset : clustersize;
  226.     
  227.       canwrite=MIN(clustersize-offset,count);
  228.       memcpy_fromfs(&(clusterd[offset]),b,canwrite);
  229.       sektor= lastcluster==0 ? 0 :
  230.                  dbl_mdfat_cluster2sector(inode->i_sb,lastcluster,cvfnr);
  231.                  
  232.       /* habe ich ueber das ende hinausgeschrieben ? */
  233.       if(canwrite+offset>length)
  234.       { /*printk("DMSDOS: write_file: write beyond file end, appending.\n");
  235.         */
  236.         length=canwrite+offset;
  237.       }
  238.       if(length>clustersize)
  239.       { printk("DMSDOS: write_file: length>clustersize ??? bug !!!\n");
  240.         length=clustersize; 
  241.       }
  242.        
  243.       /*printk("DMSDOS: write_file: writing cluster %d...\n",cluster);*/
  244.       if(dmsdos_write_cluster(inode->i_sb,clusterd,length,cluster,
  245.                               sektor,cvfnr,uc)<0)
  246.         { printk("DMSDOS: write_file: cluster write failed!\n");
  247.           break;
  248.         }
  249.                                                      
  250.       offset=0;
  251.       b+=canwrite;
  252.       geschrieben+=canwrite;
  253.       count-=canwrite;
  254.       
  255.       if(count==0)break; /* braucht keinen neuen cluster mehr*/
  256.       
  257.       /* naechster cluster ? */
  258.       lastcluster=cluster;
  259.       cluster=dbl_fat_nextcluster(inode->i_sb,cluster,cvfnr,NULL);
  260.       if(cluster==-1)
  261.       { 
  262.         /*printk("DMSDOS: write_file: write_loop: allocating new cluster after cluster %d...\n",
  263.                lastcluster);*/
  264.         cluster=allocate_next_cluster(inode->i_sb,lastcluster,cvfnr);
  265.         /*printk("DMSDOS: write_file: write_loop: new cluster=%d\n",
  266.                  cluster);*/
  267.         if(cluster<=0) break;
  268.         new=1;
  269.       }
  270.     }
  271.     
  272.     FREE(clusterd);
  273.     filp->f_pos+=geschrieben;
  274.     
  275.     if(filp->f_pos>inode->i_size)
  276.     { inode->i_size=filp->f_pos;
  277.       inode->i_dirt=1;
  278.     }
  279.     
  280.     return geschrieben;
  281.         
  282. text_write:
  283.         geschrieben=0;
  284.         need_cluster=1;
  285.         cr=0;
  286.         length=0; /* avoids warning */
  287.         while(count>0||cr==1)
  288.         { if(need_cluster)
  289.           { /*printk("DMSDOS: text_write: need_cluster %d new=%d mdfat=0x%x\n",
  290.                    cluster,new,
  291.                    dbl_mdfat_value(inode->i_sb,cluster,cvfnr,NULL));
  292.             */
  293.             if(new)   /* new means cluster is new and wasn't written before*/
  294.             { length=SECTOR_SIZE; 
  295.               new=0;
  296.             }
  297.             else
  298.             {
  299.               dbl_mdfat_value(inode->i_sb,cluster,cvfnr,NULL,&mde);
  300.               length=(mde.size_hi_minus_1+1)*SECTOR_SIZE;
  301.           if(dmsdos_read_cluster(inode->i_sb,clusterd,cluster,cvfnr)<0)
  302.           { printk("DMSDOS: write_file: read_cluster failed!\n");
  303.             FREE(clusterd);
  304.             return -EIO;
  305.           }
  306.         }
  307.         need_cluster=0;
  308.           }
  309.           
  310.           if(cr==1)
  311.           { datum=10;
  312.             cr=0;
  313.           }
  314.           else
  315.           { datum=get_fs_byte(&(buf[geschrieben]));
  316.             ++geschrieben;
  317.             if(datum==10)
  318.             { datum=13;
  319.               cr=1;
  320.             }
  321.             --count;
  322.           }
  323.  
  324.           clusterd[offset++]=datum;
  325.  
  326.           ++(filp->f_pos);
  327.           if(offset>length)length=offset;
  328.           
  329.           if(offset==clustersize)
  330.           { sektor= lastcluster==0 ? 0 :
  331.                  dbl_mdfat_cluster2sector(inode->i_sb,lastcluster,cvfnr);
  332.  
  333.             if(dmsdos_write_cluster(inode->i_sb,clusterd,length,cluster,
  334.                               sektor,cvfnr,uc)<0)
  335.         { printk("DMSDOS: write_file: cluster write failed!\n");
  336.           break;
  337.         }
  338.         /*check whether end reached */
  339.         if(count==0&&cr==0)
  340.         { offset=0; /* tells that there's no rest */
  341.           break;
  342.         }
  343.             /* check whether a new cluster is needed */
  344.             lastcluster=cluster;
  345.             cluster=dbl_fat_nextcluster(inode->i_sb,cluster,cvfnr,NULL);
  346.             if(cluster==-1)
  347.             { cluster=allocate_next_cluster(inode->i_sb,lastcluster,cvfnr);
  348.               if(cluster<=0)break;
  349.               length=SECTOR_SIZE;
  350.             }
  351.             else need_cluster=1;
  352.             offset=0;
  353.           }
  354.         }
  355.         
  356.         /* check whether there's a rest to be written */
  357.         if(offset)
  358.         { sektor= lastcluster==0 ? 0 :
  359.                  dbl_mdfat_cluster2sector(inode->i_sb,lastcluster,cvfnr);
  360.  
  361.           if(dmsdos_write_cluster(inode->i_sb,clusterd,length,cluster,
  362.                               sektor,cvfnr,uc)<0)
  363.       { printk("DMSDOS: write_file: cluster write failed!\n");
  364.       }
  365.     }
  366.         
  367.         FREE(clusterd);
  368.         
  369.     if(filp->f_pos>inode->i_size)
  370.     { inode->i_size=filp->f_pos;
  371.       inode->i_dirt=1;
  372.     }
  373.     
  374.     return geschrieben;
  375. }
  376.  
  377. void dmsdos_truncatex(struct inode *inode)
  378. {
  379.     int clusternr; 
  380.     int size;
  381.     int clustersize;
  382.     int cvfnr;
  383.     int nextcluster;
  384.     int newval;
  385.  
  386.     cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  387.     if(cvfnr<0)return; /* never truncate cvf file itself */
  388.     
  389.     if(dblsb[cvfnr].s_comp==READ_ONLY)return;
  390.     
  391.     clustersize=SECTOR_SIZE*dblsb[cvfnr].s_sectperclust;
  392.     size=inode->i_size;
  393.     clusternr=MSDOS_I(inode)->i_start;
  394.  
  395.         if(size!=0)
  396.         {       
  397.           while(size>clustersize)
  398.           { clusternr=dbl_fat_nextcluster(inode->i_sb,clusternr,cvfnr,NULL);
  399.             if(clusternr<=0)break;
  400.             size-=clustersize;
  401.           }
  402.           if(clusternr>0)
  403.           { nextcluster=dbl_fat_nextcluster(inode->i_sb,clusternr,cvfnr,NULL);
  404.             newval=0xFFFF;
  405.             dbl_fat_nextcluster(inode->i_sb,clusternr,cvfnr,&newval);
  406.             if(nextcluster>0)free_chain(inode->i_sb,nextcluster,cvfnr);
  407.           }
  408.         }
  409.         else /* inode->i_size==0 */
  410.         { if(clusternr>0)free_chain(inode->i_sb,clusternr,cvfnr);
  411.           MSDOS_I(inode)->i_start=0;
  412.         }
  413.         
  414.     MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
  415.     inode->i_dirt = 1;
  416. }
  417.  
  418. void dmsdos_put_inodex(struct inode *inode)
  419. {
  420.     struct inode *depend;
  421.     struct super_block *sb;
  422.  
  423.     if (inode->i_nlink) {
  424.         /* if (MSDOS_I(inode)->i_busy);  ??? */
  425.         return;
  426.     }
  427.     inode->i_size = 0;
  428.     dmsdos_truncatex(inode);
  429.     depend = MSDOS_I(inode)->i_depend;
  430.     sb = inode->i_sb;
  431.     clear_inode(inode);
  432.     if (depend) {
  433.         if (MSDOS_I(depend)->i_old != inode) {
  434.             printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n",
  435.                 depend, inode, MSDOS_I(depend)->i_old);
  436. #ifdef __FOR_KERNEL_1_3_8x
  437.             fat_fs_panic(sb,"...");
  438. #else
  439.             fs_panic(sb,"...");
  440. #endif
  441.             return;
  442.         }
  443.         MSDOS_I(depend)->i_old = NULL;
  444.         iput(depend);
  445.     }
  446. }
  447.  
  448. void dmsdos_write_inodex(struct inode *inode)
  449. {
  450.     struct super_block *sb = inode->i_sb;
  451.     struct buffer_head *bh;
  452.     struct msdos_dir_entry *raw_entry;
  453.     int cvfnr;
  454.     int dblsector;
  455.     
  456.     cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  457.     dblsector=(inode->i_ino&DMSDOS_ORIGINO_MASK)>>4;
  458.  
  459.     inode->i_dirt = 0; /* must be done before any return */
  460.     if(cvfnr<0)return;
  461.     if(dblsb[cvfnr].s_comp==READ_ONLY)return;
  462.     if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
  463.     if (!(bh = read_dbl_sector(sb,dblsector,cvfnr))) {
  464.         printk("dev = 0x%04X, ino = %ld\n",inode->i_dev,inode->i_ino);
  465.         panic("dmsdos_write_inode: unable to read i-node block");
  466.     }
  467.     raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
  468.         [inode->i_ino & (MSDOS_DPB-1)];
  469.     if (S_ISDIR(inode->i_mode)) {
  470.         raw_entry->attr = ATTR_DIR;
  471.         raw_entry->size = 0;
  472.     }
  473.     else {
  474.         raw_entry->attr = ATTR_NONE;
  475.         raw_entry->size = CT_LE_L(inode->i_size);
  476.     }
  477.     raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
  478.         MSDOS_I(inode)->i_attrs;
  479.     raw_entry->start = CT_LE_L(MSDOS_I(inode)->i_start);
  480. #ifdef __FOR_KERNEL_1_3_8x
  481.     fat_date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
  482. #else
  483.     date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
  484. #endif
  485.     raw_entry->time = CT_LE_W(raw_entry->time);
  486.     raw_entry->date = CT_LE_W(raw_entry->date);
  487.     bh_dirty(sb,bh);
  488.     bh_free(sb,bh);
  489. }
  490.  
  491. int dmsdos_notify_changex(struct inode * inode,struct iattr * attr)
  492. {  int cvfnr;
  493.  
  494.    cvfnr=(inode->i_ino>>DMSDOS_CVFNR_BITS)-1;
  495.    if(cvfnr<0)return -EPERM; /* never change cvf file itself */    
  496.    if(dblsb[cvfnr].s_comp==READ_ONLY)return -EPERM;
  497. #ifdef __FOR_KERNEL_1_3_8x
  498.    return fat_notify_change(inode,attr);
  499. #else
  500.    return msdos_notify_change(inode,attr);
  501. #endif
  502. }
  503.  
  504. /* File creation lock. This is system-wide to avoid deadlocks in rename. */
  505. /* (rename might deadlock before detecting cross-FS moves.) */
  506.  
  507.  
  508. /* MS-DOS "device special files" */
  509.  
  510. static char *reserved_names[] = {
  511.     "CON     ","PRN     ","NUL     ","AUX     ",
  512.     "LPT1    ","LPT2    ","LPT3    ","LPT4    ",
  513.     "COM1    ","COM2    ","COM3    ","COM4    ",
  514.     NULL };
  515.  
  516. /* Characters that are undesirable in an MS-DOS file name */
  517.   
  518. static char bad_chars[] = "*?<>|\"";
  519. static char bad_if_strict[] = "+=,; ";
  520.  
  521. /* Formats an MS-DOS file name. Rejects invalid names. */
  522.  
  523. int dmsdos_format_name(char conv,const char *name,int len,char *res,
  524.   int dot_dirs)
  525. {
  526.     char *walk,**reserved;
  527.     unsigned char c;
  528.     int space;
  529.  
  530.     if (IS_FREE(name)) return -EINVAL;
  531.     if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
  532.         if (!dot_dirs) return -EEXIST;
  533.         memset(res+1,' ',10);
  534.         while (len--) *res++ = '.';
  535.         return 0;
  536.     }
  537.     space = 1; /* disallow names starting with a dot */
  538.     c = 0;
  539.     for (walk = res; len && walk-res < 8; walk++) {
  540.             c = *name++;
  541.         len--;
  542.         if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
  543.         if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
  544.           if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
  545.         if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
  546.         if (c == '.') break;
  547.         space = c == ' ';
  548.         *walk = c >= 'a' && c <= 'z' ? c-32 : c;
  549.     }
  550.     if (space) return -EINVAL;
  551.     if (conv == 's' && len && c != '.') {
  552.         c = *name++;
  553.         len--;
  554.         if (c != '.') return -EINVAL;
  555.     }
  556.     while (c != '.' && len--) c = *name++;
  557.     if (c == '.') {
  558.         while (walk-res < 8) *walk++ = ' ';
  559.         while (len > 0 && walk-res < MSDOS_NAME) {
  560.             c = *name++;
  561.             len--;
  562.             if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
  563.             if (conv == 's' && strchr(bad_if_strict,c))
  564.                 return -EINVAL;
  565.             if (c < ' ' || c == ':' || c == '\\' || c == '.')
  566.                 return -EINVAL;
  567.             if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
  568.             space = c == ' ';
  569.             *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
  570.         }
  571.         if (space) return -EINVAL;
  572.         if (conv == 's' && len) return -EINVAL;
  573.     }
  574.     while (walk-res < MSDOS_NAME) *walk++ = ' ';
  575.     for (reserved = reserved_names; *reserved; reserved++)
  576.         if (!strncmp(res,*reserved,8)) return -EINVAL;
  577.     return 0;
  578. }
  579.  
  580. static struct wait_queue *creation_wait = NULL;
  581. static creation_lock = 0;
  582.  
  583.  
  584. void lock_dmsdos_creation(void)
  585. {
  586.     while (creation_lock) sleep_on(&creation_wait);
  587.     creation_lock = 1;
  588. }
  589.  
  590.  
  591. void unlock_dmsdos_creation(void)
  592. {
  593.     creation_lock = 0;
  594.     wake_up(&creation_wait);
  595. }
  596.  
  597. /* Creates a directory entry (name is already formatted). */
  598.  
  599. static int dmsdos_create_entry(struct inode *dir,char *name,int is_dir,
  600.     struct inode **result)
  601. {
  602.     struct super_block *sb = dir->i_sb;
  603.     struct buffer_head *bh;
  604.     struct msdos_dir_entry *de;
  605.     int res,ino;
  606.     int cvfnr;
  607.     int dblsector;
  608.     
  609.     if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  610.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  611.     
  612.     if(dblsb[cvfnr].s_comp==READ_ONLY)return -EPERM;
  613.  
  614.     if((res=scan_dbl_dir_4_empty(sb,MSDOS_I(dir)->i_start,cvfnr))<0)
  615.                                                               return res;
  616.     ino=res;
  617.     dblsector=(res&DMSDOS_ORIGINO_MASK)>>4;
  618.         bh=read_dbl_sector(sb,dblsector,cvfnr);
  619.         if(bh==0)return -EIO;
  620.         de=(struct msdos_dir_entry*) &(bh->b_data[(res&0xf)<<5]);
  621.     /*
  622.      * XXX all times should be set by caller upon successful completion.
  623.      */
  624.     dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  625.     dir->i_dirt = 1;
  626.     memcpy(de->name,name,MSDOS_NAME);
  627.     memset(de->unused, 0, sizeof(de->unused));
  628.     de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
  629.     de->start = 0;
  630. #ifdef __FOR_KERNEL_1_3_8x
  631.     fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
  632. #else
  633.     date_unix2dos(dir->i_mtime,&de->time,&de->date);
  634. #endif
  635.     de->size = 0;
  636.     bh_dirty(sb,bh);
  637.     if ((*result = iget(dir->i_sb,ino)) != NULL)
  638.         dmsdos_read_inode(*result);
  639.     bh_free(sb,bh);
  640.     if (!*result) return -EIO;
  641.     (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
  642.         CURRENT_TIME;
  643.     (*result)->i_dirt = 1;
  644.     return 0;
  645. }
  646.  
  647. static int dmsdos_create_entry_lfn(struct inode *dir,const char *name,int len,
  648.                                    int is_dir, struct inode **result)
  649. {
  650.     struct super_block *sb = dir->i_sb;
  651.     struct buffer_head *bh;
  652.     struct msdos_dir_entry *de;
  653.     int res,ino;
  654.     int cvfnr;
  655.     int dblsector;
  656.     
  657.     if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  658.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  659.     
  660.     if(dblsb[cvfnr].s_comp==READ_ONLY)return -EPERM;
  661.  
  662.     if((res=create_lfn_entry(sb,MSDOS_I(dir)->i_start,name,len,cvfnr))<0)
  663.                                                               return res;
  664.     ino=res;
  665.     dblsector=(res&DMSDOS_ORIGINO_MASK)>>4;
  666.         bh=read_dbl_sector(sb,dblsector,cvfnr);
  667.         if(bh==0)return -EIO;
  668.         de=(struct msdos_dir_entry*) &(bh->b_data[(res&0xf)<<5]);
  669.     /*
  670.      * XXX all times should be set by caller upon successful completion.
  671.      */
  672.     dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  673.     dir->i_dirt = 1;
  674.     memset(de->unused, 0, sizeof(de->unused));
  675.     de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
  676.     de->start = 0;
  677. #ifdef __FOR_KERNEL_1_3_8x
  678.     fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
  679. #else
  680.     date_unix2dos(dir->i_mtime,&de->time,&de->date);
  681. #endif
  682.     de->size = 0;
  683.     bh_dirty(sb,bh);
  684.     if ((*result = iget(dir->i_sb,ino)) != NULL)
  685.         dmsdos_read_inode(*result);
  686.     bh_free(sb,bh);
  687.     if (!*result) return -EIO;
  688.     (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
  689.         CURRENT_TIME;
  690.     (*result)->i_dirt = 1;
  691.     return 0;
  692. }
  693.  
  694. int dmsdos_createx(struct inode *dir,const char *name,int len,int mode,
  695.     struct inode **result)
  696. {
  697.     struct super_block *sb = dir->i_sb;
  698.     char msdos_name[MSDOS_NAME];
  699.     int res;
  700.     int cvfnr;
  701.     
  702.     if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  703.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  704.     
  705.     if(dblsb[cvfnr].s_comp==READ_ONLY)
  706.     { iput(dir);
  707.       return -EPERM;
  708.     }
  709.  
  710.     if (!dir) return -ENOENT;
  711.     
  712.     /* ok, now decide whether short or long */
  713.     
  714.     if(dblsb[cvfnr].s_support_lfn&1)
  715.     { lock_dmsdos_creation();
  716.       if(scan_dbl_dir_4_lfn(sb,MSDOS_I(dir)->i_start,name,len,cvfnr,
  717.                             NULL)>=0)
  718.       { unlock_dmsdos_creation();
  719.         iput(dir);
  720.         return -EEXIST;
  721.       }
  722.       res=dmsdos_create_entry_lfn(dir,name,len,S_ISDIR(mode),result);
  723.       unlock_dmsdos_creation();
  724.       iput(dir);
  725.       return res;
  726.     }
  727.     
  728.     if ((res = dmsdos_format_name(MSDOS_SB(dir->i_sb)->
  729. #ifdef __FOR_KERNEL_1_3_8x
  730.             options.name_check,
  731. #else
  732.         name_check,
  733. #endif
  734.         name,len,
  735.         msdos_name,0)) < 0) {
  736.         iput(dir);
  737.         return res;
  738.     }
  739.     lock_dmsdos_creation();
  740.     if (scan_dbl_dir_4_filename(sb,MSDOS_I(dir)->i_start,
  741.                                 msdos_name,RAW,cvfnr) >= 0) {
  742.         unlock_dmsdos_creation();
  743.         iput(dir);
  744.         return -EEXIST;
  745.      }
  746.     res = dmsdos_create_entry(dir,msdos_name,S_ISDIR(mode),result);
  747.     unlock_dmsdos_creation();
  748.     iput(dir);
  749.     return res;
  750. }
  751.  
  752. int dmsdos_mkdirx(struct inode *dir,const char *name,int len,int mode)
  753. {
  754.     struct super_block *sb = dir->i_sb;
  755.     struct inode *inode,*dot;
  756.     char msdos_name[MSDOS_NAME];
  757.     int res,ec,i;
  758.     int cvfnr;
  759.     char name_ec[257];
  760.     
  761.     if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  762.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  763.     
  764.     if(dblsb[cvfnr].s_comp==READ_ONLY)
  765.     { iput(dir);
  766.       return -EPERM;
  767.     }
  768.  
  769.         if(dblsb[cvfnr].s_support_lfn&1) /* longname */
  770.         { lock_dmsdos_creation();
  771.       if(scan_dbl_dir_4_lfn(sb,MSDOS_I(dir)->i_start,name,len,cvfnr,
  772.                             NULL)>=0)
  773.       { unlock_dmsdos_creation();
  774.         iput(dir);
  775.         return -EEXIST;
  776.       }
  777.       if((res=dmsdos_create_entry_lfn(dir,name,len,1,&inode))<0)
  778.       { unlock_dmsdos_creation();
  779.         iput(dir);
  780.         return res;
  781.       }
  782.         }
  783.  
  784.         else /* shortname */
  785.         {
  786.       if ((res = dmsdos_format_name(MSDOS_SB(dir->i_sb)->
  787. #ifdef __FOR_KERNEL_1_3_8x
  788.         options.name_check,
  789. #else
  790.         name_check,
  791. #endif
  792.         name,len,
  793.         msdos_name,0)) < 0) {
  794.         iput(dir);
  795.         return res;
  796.       }
  797.       lock_dmsdos_creation();
  798.       if (scan_dbl_dir_4_filename(sb,MSDOS_I(dir)->i_start,
  799.                                   msdos_name,RAW,cvfnr) >= 0) {
  800.         unlock_dmsdos_creation();
  801.         iput(dir);
  802.         return -EEXIST;
  803.        }
  804.       if ((res = dmsdos_create_entry(dir,msdos_name,1,&inode)) < 0) {
  805.         unlock_dmsdos_creation();
  806.         iput(dir);
  807.         return res;
  808.       }
  809.     } /* now for both long and short name */
  810.     
  811.     dir->i_nlink++;
  812.     inode->i_nlink = 2; /* no need to mark them dirty */
  813.     MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
  814.     
  815.     if ((res = allocate_first_dir_cluster(sb,cvfnr)) < 0) goto mkdir_error;
  816.     MSDOS_I(inode)->i_start=res;
  817.     inode->i_size=dblsb[cvfnr].s_sectperclust*SECTOR_SIZE;
  818.     inode->i_dirt=1;
  819.     if ((res = dmsdos_create_entry(inode,MSDOS_DOT,1,&dot)) < 0)
  820.         goto mkdir_error;
  821.     dot->i_size = inode->i_size; /* doesn't grow in the 2nd create_entry */
  822.     MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
  823.     dot->i_nlink = inode->i_nlink;
  824.     dot->i_dirt = 1;
  825.     iput(dot);
  826.     if ((res = dmsdos_create_entry(inode,MSDOS_DOTDOT,1,&dot)) < 0)
  827.         goto mkdir_error;
  828.     unlock_dmsdos_creation();
  829.     dot->i_size = dir->i_size;
  830.     MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
  831.     dot->i_nlink = dir->i_nlink;
  832.     dot->i_dirt = 1;
  833.     MSDOS_I(inode)->i_busy = 0;
  834.     iput(dot);
  835.     iput(inode);
  836.     iput(dir);
  837.     return 0;
  838. mkdir_error:
  839.     iput(inode);
  840.     if ((ec=dmsdos_rmdirx(dir,name,len)) < 0)
  841.     { for(i=0;i<len;++i)name_ec[i]=name[i];
  842.       name_ec[len]='\0';
  843.       printk("DMSDOS: rmdir %s in mkdir failed with error code %d - check filesystem\n",
  844.              name_ec,ec);
  845. #ifdef __FOR_KERNEL_1_3_8x
  846.         fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
  847. #else
  848.         fs_panic(dir->i_sb,"rmdir in mkdir failed");
  849. #endif
  850.         }
  851.     unlock_dmsdos_creation();
  852.     return res;
  853. }
  854.  
  855. /* tests whether dir empty */
  856. static int dmsdos_empty(struct inode *dir)
  857. {
  858.     loff_t pos;
  859.     unsigned char buf[32];
  860.     struct msdos_dir_entry *de;
  861.  
  862.     if (dir->i_count > 1)
  863.         return -EBUSY;
  864.     if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
  865.         pos=0;
  866.         while (dmsdos_get_entry(dir,&pos,buf) > -1)
  867.         {       de=(struct msdos_dir_entry*) buf;
  868.             if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
  869.                 MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
  870.                 MSDOS_NAME))
  871.                 return -ENOTEMPTY;        
  872.         }
  873.     }
  874.     return 0;
  875. }
  876.  
  877. int dmsdos_rmdirx(struct inode *dir,const char *name,int len)
  878. {
  879.     struct super_block *sb = dir->i_sb;
  880.     int res,ino;
  881.     struct buffer_head *bh;
  882.     struct inode *inode;
  883.     int cvfnr;
  884.  
  885.     bh = NULL;
  886.     inode = NULL;
  887.     res = -EPERM;
  888.     if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
  889.         goto rmdir_done;
  890.         
  891.     if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  892.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  893.     
  894.     if(dblsb[cvfnr].s_comp==READ_ONLY)
  895.     { iput(dir); 
  896.       return -EPERM;
  897.     }
  898.     
  899.     /*                                
  900.     if ((res = scan_dbl_dir_4_filename(sb,MSDOS_I(dir)->i_start,
  901.                                    name,len,cvfnr)) < 0) goto rmdir_done;
  902.     */
  903.     
  904.     if ((res = scan_dbl_dir_4_lfn(sb,MSDOS_I(dir)->i_start,
  905.                            name,len,cvfnr,NULL)) < 0) goto rmdir_done;
  906.  
  907.     ino=res; /* ino of entry that is being deleted */
  908.     res = -ENOENT;
  909.     if (!(inode = iget(dir->i_sb,ino))) 
  910.     { printk("DMSDOS: rmdir: couldn't get inode\n");
  911.       goto rmdir_done;
  912.     }
  913.     res = -ENOTDIR;
  914.     if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
  915.     res = -EBUSY;
  916.     if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done;
  917.     res = dmsdos_empty(inode);
  918.     if (res)
  919.         goto rmdir_done;
  920.     inode->i_nlink = 0;
  921.     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  922.     dir->i_nlink--;
  923.     inode->i_dirt = dir->i_dirt = 1;
  924.     /*
  925.     bh=read_dbl_sector(sb,(ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  926.     if(bh==NULL){res=-EIO;goto rmdir_done;}
  927.     bh->b_data[32*(ino&0xF)] = DELETED_FLAG;
  928.     bh_dirty(sb,bh);
  929.     bh_free(sb,bh);
  930.     res = 0;
  931.     */
  932.     res=remove_lfn_entry(sb,MSDOS_I(dir)->i_start,name,len,cvfnr);
  933. rmdir_done:
  934.     iput(dir);
  935.     iput(inode);
  936.     return res;
  937. }
  938.  
  939. static int dmsdos_unlink_x(
  940.     struct inode *dir,
  941.     const char *name,
  942.     int len,
  943.     int nospc)    /* Flag special file ? */
  944. {
  945.     struct super_block *sb = dir->i_sb;
  946.     int res,ino;
  947.     struct buffer_head *bh;
  948.     struct inode *inode;
  949.     int cvfnr;
  950.  
  951.     bh = NULL;
  952.     inode = NULL;
  953.  
  954.         if((cvfnr=dbltest(dir))!=0)cvfnr=(cvfnr>>DMSDOS_CVFNR_BITS)-1;
  955.     else cvfnr=(dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  956.     
  957.     if(dblsb[cvfnr].s_comp==READ_ONLY)
  958.     { iput(dir);
  959.       return -EPERM;
  960.     }
  961.  
  962.         /*
  963.     if ((res = scan_dbl_dir_4_filename(sb,MSDOS_I(dir)->i_start,
  964.                                        name,len,cvfnr)) < 0)
  965.                                         goto unlink_done;
  966.     */
  967.     
  968.     if ((res = scan_dbl_dir_4_lfn(sb,MSDOS_I(dir)->i_start,
  969.                                   name,len,cvfnr,NULL)) < 0)
  970.                                             goto unlink_done;
  971.                                                                                                        
  972.     ino=res;
  973.     
  974.     if (!(inode = iget(dir->i_sb,ino))) {
  975.         res = -ENOENT;
  976.         goto unlink_done;
  977.     }
  978.     if (!S_ISREG(inode->i_mode) && nospc){
  979.         res = -EPERM;
  980.         goto unlink_done;
  981.     }
  982.     inode->i_nlink = 0;
  983.     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  984.     MSDOS_I(inode)->i_busy = 1;
  985.     inode->i_dirt = dir->i_dirt = 1;
  986.     /*
  987.     bh=read_dbl_sector(sb,(ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  988.     if(bh==NULL){res=-EIO;goto unlink_done;}
  989.     bh->b_data[32*(ino&0xf)] = DELETED_FLAG;
  990.     bh_dirty(sb,bh);
  991.     bh_free(sb,bh);
  992.     res=0;
  993.     */
  994.     res=remove_lfn_entry(sb,MSDOS_I(dir)->i_start,name,len,cvfnr);
  995. unlink_done:
  996.     iput(inode);
  997.     iput(dir);
  998.     return res;
  999. }
  1000.  
  1001. int dmsdos_unlinkx(struct inode *dir,const char *name,int len)
  1002. {
  1003.     return dmsdos_unlink_x (dir,name,len,1);
  1004. }
  1005. /*
  1006.     Special entry for umsdos
  1007. */
  1008. int dmsdos_unlink_umsdos(struct inode *dir,const char *name,int len)
  1009. {       if(dostest(dir)) return msdos_unlink_umsdos(dir,name,len);
  1010.     return dmsdos_unlink_x (dir,name,len,0);
  1011. }
  1012.  
  1013. static int rename_same_dir(struct inode *dir, const char*new_name, int new_len,
  1014.        char *new_msdos_name,int old_ino,int cvfnr)
  1015. {
  1016.     struct super_block *sb = dir->i_sb;
  1017.     struct buffer_head *new_bh,*old_bh;
  1018.     struct msdos_dir_entry *new_de,*old_de;
  1019.     struct inode *new_inode,*old_inode;
  1020.     int new_ino,exists,error;
  1021.  
  1022.     exists = (new_ino=scan_dbl_dir_4_filename(sb,
  1023.                                               MSDOS_I(dir)->i_start,
  1024.                                               new_msdos_name/*new_name*/,
  1025.                                               RAW/*new_len*/,
  1026.                                               cvfnr)
  1027.              )  >= 0;
  1028.     old_bh=read_dbl_sector(sb,(old_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1029.     if(old_bh==NULL)return -EIO;
  1030.     old_de=(struct msdos_dir_entry*) &(old_bh->b_data[32*(old_ino&0xf)]);
  1031.     
  1032.     if (*(unsigned char *) old_de->name == DELETED_FLAG)
  1033.             { bh_free(sb,old_bh);
  1034.               return -ENOENT;
  1035.             }
  1036.             
  1037.     if (exists) {
  1038.         if (!(new_inode = iget(dir->i_sb,new_ino))) 
  1039.         { bh_free(sb,old_bh);
  1040.           return -EIO;
  1041.         }
  1042.  
  1043.         error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
  1044.             dmsdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
  1045.             ? -EPERM : 0;
  1046.             
  1047.         if (error) {
  1048.             iput(new_inode);
  1049.             bh_free(sb,old_bh);
  1050.             return error;
  1051.         }
  1052.         if (S_ISDIR(new_inode->i_mode)) {
  1053.             dir->i_nlink--;
  1054.             dir->i_dirt = 1;
  1055.         }
  1056.         
  1057.         new_inode->i_nlink = 0;
  1058.         MSDOS_I(new_inode)->i_busy = 1;
  1059.         new_inode->i_dirt = 1;
  1060.         new_bh=read_dbl_sector(sb,(new_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1061.         if(new_bh==NULL)
  1062.         { iput(new_inode);
  1063.           bh_free(sb,old_bh);
  1064.           return -EIO;
  1065.         }
  1066.         new_de=(struct msdos_dir_entry*)
  1067.                                 &(new_bh->b_data[32*(new_ino&0xf)]);
  1068.         new_de->name[0] = DELETED_FLAG;
  1069.         bh_dirty(sb,new_bh);
  1070.         iput(new_inode);
  1071.         bh_free(sb,new_bh);
  1072.     }
  1073.     memcpy(old_de->name,new_msdos_name,MSDOS_NAME);
  1074.     bh_dirty(sb,old_bh);
  1075.     bh_free(sb,old_bh);
  1076.  
  1077. /* this update code seems to be always necessary in 1.3.8x kernels -- why? */
  1078. #ifndef __FOR_KERNEL_1_3_8x
  1079.     if (MSDOS_SB(dir->i_sb)->conversion == 'a') /* update binary info */
  1080. #endif
  1081.         if ((old_inode = iget(dir->i_sb,old_ino)) != NULL) {
  1082.             dmsdos_read_inode(old_inode);
  1083.             iput(old_inode);
  1084.         }
  1085.     return 0;
  1086. }
  1087.  
  1088. static int rename_diff_dir(struct inode *old_dir,struct inode* new_dir,
  1089.         const char *new_name,int new_len,char *new_msdos_name,int old_ino,
  1090.         int cvfnr)
  1091. {
  1092.     struct super_block *sb = old_dir->i_sb;
  1093.     struct buffer_head *new_bh,*free_bh,*dotdot_bh,*old_bh;
  1094.     struct msdos_dir_entry *new_de,*free_de,*dotdot_de,*old_de;
  1095.     struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
  1096.     int new_ino,free_ino,dotdot_ino;
  1097.     int error,exists,ino;
  1098.     int dotdotsector;
  1099.  
  1100.     if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
  1101.     if (old_ino == new_dir->i_ino) return -EINVAL;
  1102.     if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
  1103.     
  1104.     /* the following loop returns -EINVAL if new_dir is anywhere a
  1105.        sub-(sub-sub-...)directory if old_ino (not old_dir)
  1106.        ...no problem if old_ino is in fact a file, ok */
  1107.     while (walk->i_ino != MSDOS_ROOT_INO) {
  1108.         ino = dmsdos_parent_ino(walk);
  1109.         iput(walk);
  1110.         if (ino < 0) return ino;
  1111.         if (ino == old_ino) return -EINVAL;
  1112.         if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
  1113.     }
  1114.     iput(walk);
  1115.     
  1116.     /* getting free entry in new_dir */
  1117.     error=scan_dbl_dir_4_empty(sb,MSDOS_I(new_dir)->i_start,cvfnr);
  1118.     if(error<0)return error;
  1119.     free_ino=error;
  1120.     
  1121.     exists = (new_ino=scan_dbl_dir_4_filename(sb,
  1122.                                               MSDOS_I(new_dir)->i_start,
  1123.                                               new_msdos_name/*new_name*/,
  1124.                                               RAW/*new_len*/,
  1125.                                               cvfnr)
  1126.              ) >= 0;
  1127.              
  1128.     if (!(old_inode = iget(old_dir->i_sb,old_ino))) return -EIO;
  1129.     
  1130.     if(dbltest(old_inode))      /* cannot move dbl root dir */
  1131.             { iput(old_inode);
  1132.               return -EPERM;
  1133.             }
  1134.     
  1135.     old_bh=read_dbl_sector(sb,(old_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1136.     if(old_bh==NULL){iput(old_inode);return -EIO;}
  1137.     old_de=(struct msdos_dir_entry*) &(old_bh->b_data[32*(old_ino&0xf)]);
  1138.     
  1139.     if (*(unsigned char *) old_de->name == DELETED_FLAG) {
  1140.         iput(old_inode);
  1141.         bh_free(sb,old_bh);
  1142.         return -ENOENT;
  1143.     }
  1144.     
  1145.     new_inode = NULL; /* to make GCC happy */
  1146.     if (exists) {
  1147.         if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
  1148.             iput(old_inode);
  1149.             bh_free(sb,old_bh);
  1150.             return -EIO;
  1151.         }
  1152.         
  1153.         error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
  1154.             dmsdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
  1155.             ? -EPERM : 0;
  1156.         if (error) {
  1157.             iput(new_inode);
  1158.             iput(old_inode);
  1159.             bh_free(sb,old_bh);
  1160.             return error;
  1161.         }
  1162.         
  1163.         new_inode->i_nlink = 0;
  1164.         MSDOS_I(new_inode)->i_busy = 1;
  1165.         new_inode->i_dirt = 1;
  1166.         new_bh=read_dbl_sector(sb,(new_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1167.         if(new_bh==NULL)
  1168.         { iput(new_inode);
  1169.           iput(old_inode);
  1170.           bh_free(sb,old_bh);
  1171.           return -EIO;
  1172.         }
  1173.         new_de=(struct msdos_dir_entry*)
  1174.                                  &(new_bh->b_data[32*(new_ino&0xf)]);
  1175.         new_de->name[0] = DELETED_FLAG;
  1176.         bh_dirty(sb,new_bh);
  1177.         bh_free(sb,new_bh);
  1178.     }
  1179.     
  1180.     free_bh=read_dbl_sector(sb,(free_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1181.     if(free_bh==NULL)
  1182.     { if(exists)iput(new_inode);
  1183.       bh_free(sb,old_bh);
  1184.       return -EIO;
  1185.     }
  1186.     free_de=(struct msdos_dir_entry*)&(free_bh->b_data[32*(free_ino&0xf)]);
  1187.     memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
  1188.     memcpy(free_de->name,new_msdos_name,MSDOS_NAME);
  1189.     if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
  1190.         free_de->name[0] = DELETED_FLAG;
  1191. /*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
  1192.         bh_free(sb,free_bh);
  1193.         if (exists) {
  1194.             iput(new_inode);
  1195.         }
  1196.         bh_free(sb,old_bh);
  1197.         return -EIO;
  1198.     }
  1199.     if (exists && S_ISDIR(new_inode->i_mode)) {
  1200.         new_dir->i_nlink--;
  1201.         new_dir->i_dirt = 1;
  1202.     }
  1203.     dmsdos_read_inode(free_inode);
  1204.     MSDOS_I(old_inode)->i_busy = 1;
  1205.     /*cache_inval_inode(old_inode);*/
  1206.     old_inode->i_dirt = 1;
  1207.     old_de->name[0] = DELETED_FLAG;
  1208.     bh_dirty(sb,old_bh);
  1209.     bh_dirty(sb,free_bh);
  1210.     bh_free(sb,old_bh);
  1211.     bh_free(sb,free_bh);
  1212.     if (!exists) iput(free_inode);
  1213.     else {
  1214.         MSDOS_I(new_inode)->i_depend = free_inode;
  1215.         MSDOS_I(free_inode)->i_old = new_inode;
  1216.         /* free_inode is put when putting new_inode */
  1217.         iput(new_inode);
  1218.         /*bh_free(sb,new_bh); is already done above */
  1219.     }
  1220.     
  1221.     if (S_ISDIR(old_inode->i_mode)) {
  1222.             /* update .. entry in old_inode which is a dir inode */
  1223.             
  1224.             dotdotsector=dbl_mdfat_cluster2sector(sb,
  1225.                                  MSDOS_I(old_inode)->i_start,cvfnr);
  1226.             dotdot_bh=read_dbl_sector(sb,dotdotsector,cvfnr);
  1227.             if(dotdot_bh==NULL){error=-EIO;goto rename_done;}
  1228.             dotdot_de=(struct msdos_dir_entry*)
  1229.                                              &(dotdot_bh->b_data[32]);
  1230.             
  1231.         dotdot_ino=(dotdotsector<<4)+1+((cvfnr+1)<<DMSDOS_CVFNR_BITS);
  1232.         if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
  1233.             error = -EIO;
  1234.             goto rename_done;
  1235.         }
  1236.         dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
  1237.             MSDOS_I(new_dir)->i_start;
  1238.         dotdot_inode->i_dirt = 1;
  1239.         bh_dirty(sb,dotdot_bh);
  1240.         old_dir->i_nlink--;
  1241.         new_dir->i_nlink++;
  1242.         /* no need to mark them dirty */
  1243.         dotdot_inode->i_nlink = new_dir->i_nlink;
  1244.         iput(dotdot_inode);
  1245.         bh_free(sb,dotdot_bh);
  1246.     }
  1247.     error = 0;
  1248. rename_done:
  1249.     iput(old_inode);
  1250.     return error;
  1251. }
  1252.  
  1253. /* the same for long filenames */
  1254. /* no difference for same directories ... */
  1255.  
  1256. static int rename_dir_lfn(struct inode *old_dir,struct inode* new_dir,
  1257.                             int cvfnr,int old_ino,
  1258.                             const char *old_name, int old_len,
  1259.                             const char *new_name, int new_len)
  1260. {
  1261.     struct super_block *sb = old_dir->i_sb;
  1262.     struct buffer_head /* *new_bh, */ *free_bh,*dotdot_bh,*old_bh;
  1263.     struct msdos_dir_entry /* *new_de, */ *free_de,*dotdot_de,*old_de;
  1264.     struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
  1265.     int new_ino,free_ino,dotdot_ino;
  1266.     int error,exists,ino;
  1267.     int dotdotsector;
  1268.     unsigned char new_msdos_name[MSDOS_NAME];
  1269.  
  1270.     if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
  1271.     if (old_ino == new_dir->i_ino) return -EINVAL;
  1272.     
  1273.     if (old_dir->i_ino != new_dir->i_ino)
  1274.     { /* this is the only difference between same_dir and diff_dir */
  1275.       if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
  1276.     
  1277.         /* the following loop returns -EINVAL if new_dir is anywhere a
  1278.          sub-(sub-sub-...)directory if old_ino (not old_dir)
  1279.          ...no problem if old_ino is in fact a file, ok */
  1280.       while (walk->i_ino != MSDOS_ROOT_INO) {
  1281.         ino = dmsdos_parent_ino(walk);
  1282.         iput(walk);
  1283.         if (ino < 0) return ino;
  1284.         if (ino == old_ino) return -EINVAL;
  1285.         if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
  1286.       }
  1287.       iput(walk);
  1288.     }
  1289.     
  1290.     /* getting free entry in new_dir and write lfn ATTR_VOLs */
  1291.     error=create_lfn_entry(sb,MSDOS_I(new_dir)->i_start,
  1292.                            new_name,new_len,cvfnr);
  1293.     if(error<0)return error;
  1294.     free_ino=error;
  1295.     
  1296.     /* this _doesn't_ find the above created entry 
  1297.        because create_lfn_entry marks even the short name entry
  1298.        with ATTR_VOL */
  1299.     exists = (new_ino=scan_dbl_dir_4_lfn(sb,
  1300.                                               MSDOS_I(new_dir)->i_start,
  1301.                                               new_name,
  1302.                                               new_len,
  1303.                                               cvfnr,NULL)
  1304.              ) >= 0;
  1305.              
  1306.     if (!(old_inode = iget(old_dir->i_sb,old_ino))) return -EIO;
  1307.     
  1308.     if(dbltest(old_inode))      /* cannot move dbl root dir */
  1309.             { iput(old_inode);
  1310.               return -EPERM;
  1311.             }
  1312.     
  1313.     old_bh=read_dbl_sector(sb,(old_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1314.     if(old_bh==NULL){iput(old_inode);return -EIO;}
  1315.     old_de=(struct msdos_dir_entry*) &(old_bh->b_data[32*(old_ino&0xf)]);
  1316.     
  1317.     if (*(unsigned char *) old_de->name == DELETED_FLAG) {
  1318.         iput(old_inode);
  1319.         bh_free(sb,old_bh);
  1320.         return -ENOENT;
  1321.     }
  1322.     
  1323.     new_inode = NULL; /* to make GCC happy */
  1324.     if (exists) {
  1325.         if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
  1326.             iput(old_inode);
  1327.             bh_free(sb,old_bh);
  1328.             return -EIO;
  1329.         }
  1330.         
  1331.         error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ?
  1332.             dmsdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR)
  1333.             ? -EPERM : 0;
  1334.         if (error) {
  1335.             iput(new_inode);
  1336.             iput(old_inode);
  1337.             bh_free(sb,old_bh);
  1338.             return error;
  1339.         }
  1340.         
  1341.         new_inode->i_nlink = 0;
  1342.         MSDOS_I(new_inode)->i_busy = 1;
  1343.         new_inode->i_dirt = 1;
  1344.         /*
  1345.         new_bh=read_dbl_sector(sb,(new_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1346.         if(new_bh==NULL)
  1347.         { iput(new_inode);
  1348.           iput(old_inode);
  1349.           bh_free(sb,old_bh);
  1350.           return -EIO;
  1351.         }
  1352.         new_de=(struct msdos_dir_entry*)
  1353.                                  &(new_bh->b_data[32*(new_ino&0xf)]);
  1354.         new_de->name[0] = DELETED_FLAG;
  1355.         bh_dirty(sb,new_bh);
  1356.         bh_free(sb,new_bh);
  1357.         */
  1358.         if(remove_lfn_entry(sb,MSDOS_I(new_inode)->i_start,
  1359.                          new_name,new_len,cvfnr)<0)
  1360.         { iput(new_inode);
  1361.           iput(old_inode);
  1362.           bh_free(sb,old_bh);
  1363.           return -EIO;
  1364.         }
  1365.     }
  1366.     
  1367.     free_bh=read_dbl_sector(sb,(free_ino&DMSDOS_ORIGINO_MASK)>>4,cvfnr);
  1368.     if(free_bh==NULL)
  1369.     { if(exists)iput(new_inode);
  1370.       bh_free(sb,old_bh);
  1371.       return -EIO;
  1372.     }
  1373.     free_de=(struct msdos_dir_entry*)&(free_bh->b_data[32*(free_ino&0xf)]);
  1374.     
  1375.     /* copy everything except (short) name */
  1376.     /* name retten */
  1377.     memcpy(new_msdos_name,free_de->name,MSDOS_NAME);
  1378.     memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
  1379.     memcpy(free_de->name,new_msdos_name,MSDOS_NAME);
  1380.             
  1381.     if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
  1382.         free_de->name[0] = DELETED_FLAG;
  1383. /*  Don't mark free_bh as dirty. Both states are supposed to be equivalent. */
  1384.         bh_free(sb,free_bh);
  1385.         if (exists) {
  1386.             iput(new_inode);
  1387.         }
  1388.         bh_free(sb,old_bh);
  1389.         return -EIO;
  1390.     }
  1391.     if (exists && S_ISDIR(new_inode->i_mode)) {
  1392.         new_dir->i_nlink--;
  1393.         new_dir->i_dirt = 1;
  1394.     }
  1395.     dmsdos_read_inode(free_inode);
  1396.     MSDOS_I(old_inode)->i_busy = 1;
  1397.     /*cache_inval_inode(old_inode);*/
  1398.     bh_free(sb,old_bh);
  1399.     remove_lfn_entry(sb,MSDOS_I(old_dir)->i_start,
  1400.                      old_name,old_len,cvfnr);
  1401.     old_inode->i_dirt = 1;
  1402.     /*
  1403.     old_de->name[0] = DELETED_FLAG;
  1404.     bh_dirty(sb,old_bh);
  1405.     */
  1406.     bh_dirty(sb,free_bh);
  1407.     bh_free(sb,free_bh);
  1408.     if (!exists) iput(free_inode);
  1409.     else {
  1410.         MSDOS_I(new_inode)->i_depend = free_inode;
  1411.         MSDOS_I(free_inode)->i_old = new_inode;
  1412.         /* free_inode is put when putting new_inode */
  1413.         iput(new_inode);
  1414.         /*bh_free(sb,new_bh); is already done above */
  1415.     }
  1416.     
  1417.     if (S_ISDIR(old_inode->i_mode)) {
  1418.             /* update .. entry in old_inode which is a dir inode */
  1419.             
  1420.             dotdotsector=dbl_mdfat_cluster2sector(sb,
  1421.                                  MSDOS_I(old_inode)->i_start,cvfnr);
  1422.             dotdot_bh=read_dbl_sector(sb,dotdotsector,cvfnr);
  1423.             if(dotdot_bh==NULL){error=-EIO;goto rename_done;}
  1424.             dotdot_de=(struct msdos_dir_entry*)
  1425.                                              &(dotdot_bh->b_data[32]);
  1426.             
  1427.         dotdot_ino=(dotdotsector<<4)+1+((cvfnr+1)<<DMSDOS_CVFNR_BITS);
  1428.         if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
  1429.             error = -EIO;
  1430.             goto rename_done;
  1431.         }
  1432.         dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
  1433.             MSDOS_I(new_dir)->i_start;
  1434.         dotdot_inode->i_dirt = 1;
  1435.         bh_dirty(sb,dotdot_bh);
  1436.         old_dir->i_nlink--;
  1437.         new_dir->i_nlink++;
  1438.         /* no need to mark them dirty */
  1439.         dotdot_inode->i_nlink = new_dir->i_nlink;
  1440.         iput(dotdot_inode);
  1441.         bh_free(sb,dotdot_bh);
  1442.     }
  1443.     error = 0;
  1444. rename_done:
  1445.     iput(old_inode);
  1446.     return error;
  1447. }
  1448.  
  1449. int dmsdos_renamex(struct inode *old_dir,const char *old_name,int old_len,
  1450.     struct inode *new_dir,const char *new_name,int new_len
  1451. #ifdef __FOR_KERNEL_2_0_1
  1452.     , int must_be_dir
  1453. #endif
  1454.     )
  1455. {
  1456.     struct super_block *sb = old_dir->i_sb;
  1457.     char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
  1458.     int old_ino,error;
  1459.     int old_cvfnr;
  1460.     int new_cvfnr;
  1461.     
  1462.     /* cannot move from msdos to dmsdos and vice versa: 
  1463.        different partitions */
  1464.     /* maybe I have to implement a copy and delete here */
  1465.     if(dostest(old_dir)||dostest(new_dir))
  1466.     { iput(old_dir);
  1467.       iput(new_dir);
  1468.       return -EINVAL;
  1469.     }
  1470.     
  1471.     if((old_cvfnr=dbltest(old_dir))!=0)old_cvfnr=(old_cvfnr>>DMSDOS_CVFNR_BITS)-1;
  1472.     else old_cvfnr=(old_dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  1473.  
  1474.         if(dblsb[old_cvfnr].s_comp==READ_ONLY)
  1475.         { iput(old_dir);
  1476.           iput(new_dir);
  1477.           return -EPERM;
  1478.         }
  1479.     
  1480.     if((new_cvfnr=dbltest(new_dir))!=0)new_cvfnr=(new_cvfnr>>DMSDOS_CVFNR_BITS)-1;
  1481.     else new_cvfnr=(new_dir->i_ino>>DMSDOS_CVFNR_BITS)-1;
  1482.     
  1483.     if(dblsb[new_cvfnr].s_comp==READ_ONLY)
  1484.     { iput(old_dir);
  1485.       iput(new_dir);
  1486.       return -EPERM;
  1487.     }
  1488.     
  1489.     /* cannot move across cvfs: different partitions */
  1490.     /* maybe a *compressed* copy and delete ??? */
  1491.     if(old_cvfnr!=new_cvfnr)
  1492.     { iput(old_dir);
  1493.       iput(new_dir);
  1494.       return -EINVAL;
  1495.     }
  1496.     
  1497.     /* now check for lfn */
  1498.     
  1499.     if(dblsb[old_cvfnr].s_support_lfn&1)
  1500.     { if((error=scan_dbl_dir_4_lfn(sb,MSDOS_I(old_dir)->i_start,
  1501.                       old_name,old_len,old_cvfnr,NULL))<0)goto rename_done;
  1502.       old_ino=error;
  1503.       lock_dmsdos_creation();
  1504.       if(old_dir==new_dir)
  1505.         error=(old_len==new_len&&strncmp(old_name,new_name,old_len)==0) ?
  1506.                         0 :
  1507.                         rename_dir_lfn(old_dir,new_dir,old_cvfnr,old_ino,
  1508.                                old_name,old_len,new_name,new_len);
  1509.       else
  1510.         error=rename_dir_lfn(old_dir,new_dir,old_cvfnr,old_ino,
  1511.                                old_name,old_len,new_name,new_len);
  1512.       unlock_dmsdos_creation();
  1513.       goto rename_done; 
  1514.     }
  1515.     
  1516.     if ((error = dmsdos_format_name(MSDOS_SB(old_dir->i_sb)->
  1517. #ifdef __FOR_KERNEL_1_3_8x
  1518.             options.name_check,
  1519. #else
  1520.         name_check,
  1521. #endif
  1522.         old_name,old_len,old_msdos_name,1)) < 0) goto rename_done;
  1523.     if ((error = dmsdos_format_name(MSDOS_SB(new_dir->i_sb)->
  1524. #ifdef __FOR_KERNEL_1_3_8x
  1525.             options.name_check,
  1526. #else
  1527.         name_check,
  1528. #endif
  1529.         new_name,new_len,new_msdos_name,0)) < 0) goto rename_done;
  1530.     if ((error = scan_dbl_dir_4_filename(sb,MSDOS_I(old_dir)->i_start,
  1531.                       old_msdos_name/*old_name*/,RAW/*old_len*/,old_cvfnr)) < 0) goto rename_done;
  1532.     old_ino=error;
  1533.     lock_dmsdos_creation();
  1534.     if (old_dir == new_dir)
  1535.         error = strncmp(old_msdos_name,new_msdos_name,MSDOS_NAME)==0 ?
  1536.                    0 :
  1537.                    rename_same_dir(old_dir,new_name,new_len,
  1538.                                    new_msdos_name,old_ino,old_cvfnr);
  1539.     else error = rename_diff_dir(old_dir,new_dir,new_name,new_len,
  1540.                              new_msdos_name,old_ino,old_cvfnr);
  1541.     unlock_dmsdos_creation();
  1542. rename_done:
  1543.     iput(old_dir);
  1544.     iput(new_dir);
  1545.     return error;
  1546. }
  1547.